package org.cheetah.core.action.spi;

import javax.xml.bind.annotation.XmlAccessOrder;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorOrder;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

import org.cheetah.core.action.Action;
import org.cheetah.core.action.ActionContext;
import org.cheetah.core.action.ActionDefinition;
import org.cheetah.core.exchange.Exchange;
import org.cheetah.core.exchange.Message;
import org.cheetah.core.language.CompiledExpression;
import org.cheetah.core.language.Languages;

@XmlRootElement(name = "expression")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
public class ExpressionDefinition extends ActionDefinition {

	@XmlAttribute(name = "language", required = true)
	private String language;

	@XmlAttribute(name = "expression", required = true)
	private String expression;

	public ExpressionDefinition expression(String language, String expression) {
		this.language = language;
		this.expression = expression;

		return this;
	}

	public CompiledExpression compile() throws Exception {
		return Languages.compile(language.trim(), expression.trim());
	}

	public Action createAction() throws Exception {
		return new ActionImpl(Languages.compile(language.trim(), expression
				.trim()));
	}

	private static class ActionImpl implements Action {
		private CompiledExpression exp;

		ActionImpl(CompiledExpression exp) {
			this.exp = exp;
		}

		public void process(ActionContext ctx, Exchange exchange)
				throws Exception {
			Object result = exp.eval(exchange.getIn());
			if (result == null) {
				exchange.setOut(null);
			} else if (result instanceof Message) {
				exchange.setOut((Message) result);
			} else {
				exchange.setOut(new Message(result));
			}

			ctx.process(exchange);
		}
	}
}
